package domain

import (
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"gluenet/internal/glue-srvp/domain/dependency"
	"gluenet/internal/glue-srvp/domain/entity"
	"gluenet/internal/pkg/infra/prepare"
	"gluenet/modules/manager/server/infra"
)

// 创建对象，并把对象放入依赖池，架构自动构建依赖
func init() {
	prepare.RegisterService(func() {
		index := NewIndexDomain()
		prepare.InjectDependency(func() *Index {
			return index
		})
	})
}

// Index 用户首页管理领域
type Index struct {
	MetaRepo dependency.MetaRepo
}

// Put 存储首页配置
// Deprecated: 在0.3.0版本丢弃
func (r *Index) Put(user_id string, data interface{}) error {
	var index entity.Index
	err := r.MetaRepo.FindOne(&index, map[string]interface{}{
		"user_id": user_id,
	})
	if err != nil {
		return err
	}

	lines, ok := data.([]interface{})
	if !ok {
		return fmt.Errorf("data is not []interface")
	}

	idm := make(map[string]bool, len(lines))
	for _, line := range lines {
		bts, _ := json.Marshal(line)
		d := md5.Sum(bts)
		id := hex.EncodeToString(d[:])
		if _, ok = idm[id]; ok {
			return fmt.Errorf("duplicate line")
		}
		idm[id] = true
	}

	return r.MetaRepo.PutKV(index.DetailRepoKey, map[string]interface{}{
		"idmap": idm,
		"list":  lines,
	})
}

// PutV03 存储首页配置
func (r *Index) PutV03(user_id string, data interface{}) error {
	var index entity.Dict
	err := r.MetaRepo.FindOne(&index, map[string]interface{}{
		"user_id":  user_id,
		"module":   "index",
		"dict_key": "index_page",
	})

	if errors.Is(err, infra.DataNotFind) {
		index, err = r.InitV03(user_id)
		if err != nil {
			return err
		}
	}

	if err != nil {
		return err
	}

	lines, ok := data.([]interface{})
	if !ok {
		return fmt.Errorf("data is not []interface")
	}

	idm := make(map[string]interface{}, len(lines))
	for _, line := range lines {
		bts, _ := json.Marshal(line)
		d := md5.Sum(bts)
		id := hex.EncodeToString(d[:])
		if _, ok = idm[id]; ok {
			return fmt.Errorf("duplicate line")
		}
		idm[id] = true
	}

	bts, _ := json.Marshal(idx{
		IdMap: idm,
		List:  lines,
	})

	index.Value = string(bts)

	_, err = r.MetaRepo.Upt(index)
	return err
}

// Add 添加首页配置
// Deprecated: 在0.3.0版本丢弃
func (r *Index) Add(user_id string, line interface{}) error {
	var index entity.Index
	err := r.MetaRepo.FindOne(&index, map[string]interface{}{
		"user_id": user_id,
	})
	if err != nil {
		return err
	}

	var detailsi interface{}
	err = r.MetaRepo.FindKV(index.DetailRepoKey, &detailsi)
	if err != nil {
		return err
	}

	details, ok := detailsi.(map[string]interface{})
	if !ok {
		return fmt.Errorf("detail is not map[string]interface")
	}

	idm, ok := details["idmap"].(map[string]interface{})
	if !ok {
		return fmt.Errorf("detail is not contain id map")
	}
	list, ok := details["list"].([]interface{})
	if !ok {
		return fmt.Errorf("detail is not contain list")
	}

	bts, _ := json.Marshal(line)
	d := md5.Sum(bts)
	id := hex.EncodeToString(d[:])
	if _, ok = idm[id]; ok {
		return fmt.Errorf("line is exist")
	}
	idm[id] = true
	list = append(list, line)
	details["list"] = list

	return r.MetaRepo.PutKV(index.DetailRepoKey, details)
}

// AddV03 添加首页配置
func (r *Index) AddV03(user_id string, line interface{}) error {
	var index entity.Dict
	err := r.MetaRepo.FindOne(&index, map[string]interface{}{
		"user_id":  user_id,
		"module":   "index",
		"dict_key": "index_page",
	})

	if errors.Is(err, infra.DataNotFind) {
		index, err = r.InitV03(user_id)
		if err != nil {
			return err
		}
	}

	if err != nil && !errors.Is(err, infra.DataNotFind) {
		return err
	}

	var idxs idx
	if err = json.Unmarshal([]byte(index.Value), &idxs); err != nil {
		return err
	}

	idm := idxs.IdMap
	list := idxs.List

	bts, _ := json.Marshal(line)
	d := md5.Sum(bts)
	id := hex.EncodeToString(d[:])
	if _, ok := idm[id]; ok {
		return fmt.Errorf("line is exist")
	}
	idm[id] = true
	list = append(list, line)
	idxs.List = list

	bt, _ := json.Marshal(idxs)
	index.Value = string(bt)

	_, err = r.MetaRepo.Upt(index)
	return err
}

// Get 查询首页配置
// Deprecated: 在0.3.0版本丢弃
func (r *Index) Get(user_id string) (interface{}, error) {
	var index entity.Index
	err := r.MetaRepo.FindOne(&index, map[string]interface{}{
		"user_id": user_id,
	})

	if err != nil {
		return nil, err
	}

	var detailsi interface{}
	err = r.MetaRepo.FindKV(index.DetailRepoKey, &detailsi)
	if err != nil {
		return nil, err
	}

	details, ok := detailsi.(map[string]interface{})
	if !ok {
		return nil, fmt.Errorf("detail is not map[string]interface")
	}

	list, ok := details["list"].([]interface{})
	if !ok {
		return nil, fmt.Errorf("detail is not contain list")
	}

	return list, nil
}

type idx struct {
	IdMap map[string]interface{} `json:"idmap"`
	List  []interface{}          `json:"list"`
}

// GetV03 查询首页配置
func (r *Index) GetV03(user_id string) (interface{}, error) {
	var index entity.Dict
	err := r.MetaRepo.FindOne(&index, map[string]interface{}{
		"user_id":  user_id,
		"module":   "index",
		"dict_key": "index_page",
	})

	if errors.Is(err, infra.DataNotFind) {
		index, err = r.InitV03(user_id)
		if err != nil {
			return nil, err
		}
	}

	if err != nil {
		return nil, err
	}

	var idxs idx
	if err = json.Unmarshal([]byte(index.Value), &idxs); err != nil {
		return nil, err
	}

	return idxs.List, nil
}

// ReSet 重置首页配置
// Deprecated: 在0.3.0版本丢弃
func (r *Index) ReSet(user_id string) error {
	var index entity.Index
	err := r.MetaRepo.FindOne(&index, map[string]interface{}{
		"user_id": user_id,
	})

	if err != nil {
		return err
	}

	return r.MetaRepo.PutKV(index.DetailRepoKey, map[string]interface{}{
		"idmap": map[string]interface{}{},
		"list":  []interface{}{},
	})
}

// ReSetV03 重置首页配置
func (r *Index) ReSetV03(user_id string) error {
	var index entity.Dict
	err := r.MetaRepo.FindOne(&index, map[string]interface{}{
		"user_id":  user_id,
		"module":   "index",
		"dict_key": "index_page",
	})

	if errors.Is(err, infra.DataNotFind) {
		index, err = r.InitV03(user_id)
		if err != nil {
			return err
		}
	}

	if err != nil {
		return err
	}

	bts, _ := json.Marshal(idx{IdMap: make(map[string]interface{})})
	index.Value = string(bts)

	_, err = r.MetaRepo.Upt(index)
	return err
}

// InitV03 初始化首页配置
func (r *Index) InitV03(user_id string) (entity.Dict, error) {
	var dict entity.Dict
	dict.UserId = user_id
	dict.Module = "index"
	dict.Key = "index_page"

	bts, _ := json.Marshal(idx{IdMap: make(map[string]interface{})})
	dict.Value = string(bts)
	dict.Version = "v0.0.0"
	dict.Enable = true
	dict.Editable = true
	dict.Describe = "user index page config dict"

	obj, err := r.MetaRepo.Add(&dict)
	return *obj.(*entity.Dict), err
}

//func (r *Index) NewIndex(userId string) error {
//	return r.MetaRepo.PutKV(fmt.Sprintf(infra.IndexRepoKeyFormat, userId), map[string]interface{}{})
//}

func NewIndexDomain() *Index {
	domain := &Index{}
	prepare.FetchDependency(&domain.MetaRepo)
	return domain
}
